package flexserverlib.jms.spring.adapters;

import flex.messaging.messages.Message;
import flex.messaging.messages.MessagePerformanceUtils;
import flex.messaging.services.messaging.adapters.JMSConfigConstants;
import org.springframework.jms.core.MessageCreator;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Iterator;

/**
 * User: mnimer
 * Date: Oct 2, 2008
 */
public class FlexMessageCreator implements MessageCreator
{
    private Message message;
    private String messageClass;


    public FlexMessageCreator(String messageClass_, Message message_)
    {
        message = message_;
        messageClass = messageClass_;
    }


    public javax.jms.Message createMessage(Session session) throws JMSException
    {
        if (messageClass.equals(ObjectMessage.class.getName()))
        {
            return FlexToJmsObjectMessage(session, message);
        } else // if (messageClass.equals(TextMessage.class.getName()))
        {
            return FlexToJmsTextMessage(session, message);
        }
    }


    protected TextMessage FlexToJmsTextMessage(Session session, Message message) throws JMSException
    {
        TextMessage textMessage = session.createTextMessage();
        textMessage.setText(message.getBody().toString());
        copyHeaders(textMessage, message);

        return textMessage;
    }


    protected ObjectMessage FlexToJmsObjectMessage(Session session, Message message) throws JMSException
    {
        ObjectMessage objMessage = session.createObjectMessage();
        objMessage.setObject((Serializable) message.getBody());
        copyHeaders(objMessage, message);

        return objMessage;
    }


    protected void copyHeaders(javax.jms.Message message, Message flexMessage) throws JMSException
    {
        // Generic Flex headers become JMS properties, named Flex headers become JMS headers
        for (Iterator iter = flexMessage.getHeaders().keySet().iterator(); iter.hasNext();)
        {
            String propName = (String) iter.next();
            Object propValue = flexMessage.getHeader(propName);

            // For now, only named property is TTL.
            if (!propName.equals(JMSConfigConstants.TIME_TO_LIVE))
            {
                // MPI header contains a MessagePerformaceInfo object that cannot
                // be set as a JMS header property. Instead, it is broken down
                // to its primitive types and each primitive is individually
                // set as a JMS header property.
                if (propName.equals(MessagePerformanceUtils.MPI_HEADER_IN))
                {
                    Field[] fields = propValue.getClass().getFields();
                    for (int i = 0; i < fields.length; i++)
                    {
                        Field field = fields[i];
                        // Use MPI_HEADER_IN as prefix to the property name so that
                        // they can be distinguished later when the MessagePerformanceInfo
                        // object gets built from the headers.
                        String mpiPropertyName = MessagePerformanceUtils.MPI_HEADER_IN + field.getName();
                        Object mpiPropertyValue = null;
                        try
                        {
                            mpiPropertyValue = field.get(propValue);
                            message.setObjectProperty(mpiPropertyName, mpiPropertyValue);
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                            //Log.getLogger(JMSAdapter.LOG_CATEGORY).warn("JMSProducer could not retrieve the value of MessagePerformanceUtils property '" + propValue + "' from the Flex message, therefore it will not be set on the JMS message.");
                        }
                    }
                } else if (propValue != null)
                {
                    message.setObjectProperty(propName, propValue);
                }
            }
        }
    }

}
